﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Reflection;
using System.Xml;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Text.RegularExpressions;

using MP.LayerHelper.MP_OBS.DAL.DatabaseSpecific;
/// <summary>
/// Summary description for ManagerBase
/// </summary>

namespace MP.LayerHelper.MP_OBS.BLL
{
    class PropertiesField
    {
        public string Name { get; set; }
        public string Value { get; set; }
        public string TypeName { get; set; }
    }

    public class ManagerBase
    {
        public const string AcInsert = "INSERT";
        public const string AcUpdate = "UPDATE";
        public const string AcUpdateDel = "UPDATE-DEL";
        public const string AcDelete = "DELETE";
        
        string connectionString { get; set; }
        public ManagerBase()
        {
            DataAccessAdapter adapter = new DataAccessAdapter();
            connectionString = adapter.ConnectionString;
        }

        public virtual string TableName()
        {
            return "";
        }
        /// <summary>
        /// Kiem tra record nay co phai la cua account khong
        /// </summary>
        /// <param name="recordId"></param>
        /// <param name="accountID"></param>
        /// <returns></returns>
        public bool CheckRoleInRecord(Guid recordId, Guid accountID)
        {
            return ManagerBase.CheckRoleInRecord(TableName(), recordId, accountID);
        }


        public static bool CheckRoleInRecord(string tableName, Guid recordID, Guid accountID)
        {
            string sql = "SELECT * FROM " + tableName + " WHERE ID ='" + recordID + "'";
            DataTable tbl = (new ManagerBase()).ExecuteDataTable(CommandType.Text, sql);
            if (tbl == null || tbl.Rows.Count == 0)
                return false;
            if (!tbl.Columns.Contains("RecordOfAccount"))
                return true;
            return tbl.Rows[0]["RecordOfAccount"].ToString() == accountID.ToString();
        }
         

        #region Private Method
        bool IsGuid(string GuidId)
        {
            if (string.IsNullOrEmpty(GuidId))
                return false;
            string parttern = "########-####-####-####-############";
            string guid = GuidId.ToLower();

            Regex reg = new Regex(parttern.Replace("#", "[a-z0-9]"));
            if (reg.IsMatch(guid) && guid.Length == parttern.Length)
                return true;
            return false;
        }

        Guid ToGuid(string val)
        {
            if (!string.IsNullOrEmpty(val) && IsGuid(val))
                return new Guid(val);
            return Guid.Empty;
        }

        string ArrayToXml(List<PropertiesField> data)
        {
            XmlWriterSettings wSettings = new XmlWriterSettings();
            wSettings.Indent = true;
            MemoryStream ms = new MemoryStream();
            XmlWriter xw = XmlWriter.Create(ms, wSettings);// Write Declaration
            xw.WriteStartDocument();

            // Write the root node
            xw.WriteStartElement("RootLog");

            foreach (PropertiesField item in data)
            {
                xw.WriteStartElement(item.Name);
                

                xw.WriteStartAttribute("type");
                xw.WriteString(item.TypeName);
                xw.WriteEndAttribute();

                xw.WriteString(item.Value);
                xw.WriteEndElement();
            }

            xw.WriteEndElement();

            // Close the document
            xw.WriteEndDocument();

            // Flush the write
            xw.Flush();

            Byte[] buffer = new Byte[ms.Length];
            buffer = ms.ToArray();
            string xmlOutput = System.Text.Encoding.UTF8.GetString(buffer);
            return xmlOutput;
        }

        void PrepareCommand(SqlCommand cmd, SqlConnection conn, SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[] cmdParms)
        {

            if (conn.State != ConnectionState.Open)
                conn.Open();

            cmd.Connection = conn;
            cmd.CommandText = cmdText;

            if (trans != null)
                cmd.Transaction = trans;

            cmd.CommandType = cmdType;

            if (cmdParms != null)
            {
                foreach (SqlParameter parm in cmdParms)
                    cmd.Parameters.Add(parm);
            }
        }

        #endregion

        #region Public Method
        public int ExecuteNonQuery(CommandType cmdType, string cmdText)
        {
            return ExecuteNonQuery(cmdType, cmdText, null);
        }

        public int ExecuteNonQuery(CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
        {
            
            int val = 0;
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                SqlCommand cmd = new SqlCommand();
                PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
                val = cmd.ExecuteNonQuery();
                cmd.Parameters.Clear();
                conn.Close();
            }
            return val;
        }

        public DataTable ExecuteDataTable(CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
        {

            DataTable dt = new DataTable();
            using (SqlConnection conn = new SqlConnection(connectionString))
            {

                SqlCommand cmd = new SqlCommand();

                PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
                SqlDataAdapter da = new SqlDataAdapter(cmd);
                da.Fill(dt);
                da.Dispose();
                cmd.Parameters.Clear();
                conn.Close();
            }
            return dt;
        }
        #endregion

        public void LogEntity(Object logObj, Object structure, string action)
        {
            LogEntity(logObj, action, "");
        }

        public void LogEntity(Object logObj, Object structure, string action, string controlId)
        {
            PropertyInfo[] fields = structure.GetType().GetProperties();
            List<PropertiesField> data = new List<PropertiesField>();
            Guid recordId = new Guid();

            for (int i = 0; i < fields.Length; i++)
            {
                string value = "";
                PropertyInfo info = logObj.GetType().GetProperty(fields[i].Name);
                try
                {
                    value = info.GetValue(logObj, null).ToString();
                }
                catch { }
                data.Add(new PropertiesField { Name = info.Name, Value = value, TypeName = info.PropertyType.FullName });
                if (fields[i].Name.ToUpper() == "ID")
                {
                    recordId = ToGuid(value);
                }

                if (fields[i].Name.ToLower() == "isdeleted" || fields[i].Name.ToLower() == "isdelete")
                {
                    if (value.ToLower() == "true")
                        action = ManagerBase.AcUpdateDel;
                }
            }

            /* // cach viet cu
            for (int i = 0; i < fields.Length; i++)
            {
                string value = "";
                if (fields[i].Module.Name == logObj.GetType().Module.Name && fields[i].PropertyType.Namespace.ToLower() == "system" && !fields[i].Name.Contains("LLBLGenPro"))
                {
                    try
                    {
                        value = fields[i].GetValue(logObj, null).ToString();
                    }
                    catch { }
                    data.Add(fields[i].Name, value);
                    if (fields[i].Name.ToUpper() == "ID")
                    {
                        recordId = ToGuid(value);
                    }

                    if (fields[i].Name.ToLower() == "isdeleted" || fields[i].Name.ToLower() == "isdelete")
                    {
                        if (value.ToLower() == "true")
                            action = ManagerBase.AcUpdateDel;
                    }
                }
            }
            */
            if (data.Count > 0)
            {
                string xmldatalog = ArrayToXml(data);
                string tableName = logObj.GetType().Name;
                tableName = tableName.Substring(0, tableName.Length - 6);

                string strSQL = "lg_LogObject";
                SqlParameter[] param = new SqlParameter[8];
                param[0] = new SqlParameter("@UserName", HttpContext.Current.User.Identity.Name);
                param[1] = new SqlParameter("@RecordId", recordId);
                param[2] = new SqlParameter("@DataLog", xmldatalog);
                param[3] = new SqlParameter("@TableName", tableName);
                param[4] = new SqlParameter("@PageUrl", HttpContext.Current.Request.RawUrl);
                param[5] = new SqlParameter("@ControlId", controlId);
                param[6] = new SqlParameter("@Action", action);
                param[7] = new SqlParameter("@ClientIp", HttpContext.Current.Request.UserHostAddress);

                ExecuteNonQuery(CommandType.StoredProcedure, strSQL, param);
            }
        }
    }
}